package com.baizw.cultivation.util;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.baizw.cultivation.enums.PermissionEnum;
import com.baizw.cultivation.module.admin.entity.vo.UserMenu;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 权限工具类
 *
 * @author 剧终1204
 * @version V1.0
 * @date 2020年04月27日 15:05
 */
@Slf4j
public class PermissionUtil {

    /**
     * 计算二进制权限
     *
     * @param binary 二进制权限
     * @return
     */
    public static List<Map<String, Object>> convert(String binary) {
        List<Map<String, Object>> permissionList = new ArrayList<>();
        if (StrUtil.isNotBlank(binary)) {
            int binaryToInt = NumberUtil.binaryToInt(binary);
            LinkedHashMap<String, PermissionEnum> linkedHashMap = EnumUtil.getEnumMap(PermissionEnum.class);
            for (PermissionEnum permission : linkedHashMap.values()) {
                int mark = permission.getMark();
                if ((binaryToInt & mark) == mark) {
                    permissionList.add(BeanUtil.beanToMap(permission));
                }
            }
        }
        return permissionList;
    }

    /**
     * 根据二进制权限获取操作类型
     *
     * @param permission 二进制权限
     * @return
     */
    public static List<String> actionFromPermission(String permission) {
        if (StrUtil.isBlank(permission)) {
            return Collections.emptyList();
        }
        int binaryToInt = NumberUtil.binaryToInt(permission);
        LinkedHashMap<String, PermissionEnum> linkedHashMap = EnumUtil.getEnumMap(PermissionEnum.class);
        return linkedHashMap.values().parallelStream()
                .filter(x -> (binaryToInt & x.getMark()) == x.getMark())
                .map(PermissionEnum::getAction).collect(Collectors.toList());
    }

    /**
     * 组装Shiro需要的权限标识
     *
     * @param permissions 资源集合
     * @return Set<String>
     */
    public static Set<String> hasPermission(List<UserMenu> permissions) {
        String permissionTemplate = "{}:{}";
        Set<String> permissionSet = new HashSet<>(16);
        LinkedHashMap<String, PermissionEnum> linkedHashMap = EnumUtil.getEnumMap(PermissionEnum.class);
        if (CollUtil.isNotEmpty(permissions)) {
            for (UserMenu userMenu : permissions) {
                String resourceName = userMenu.getName();
                String permissionString = userMenu.getPermission();
                int binary = NumberUtil.binaryToInt(permissionString);
                for (PermissionEnum permission : linkedHashMap.values()) {
                    int mark = permission.getMark();
                    if ((binary & mark) == mark) {
                        String add = StrUtil.format(permissionTemplate, resourceName, permission.getAction());
                        permissionSet.add(add);
                    }
                }
            }
        }
        return permissionSet;
    }

    /**
     * 将操作权限转化为对应的权限二进制
     *
     * @param actions 操作类型
     * @return 二进制权限
     */
    public static String buildPermissionString(List<String> actions) {
        int number = 0;
        if (CollUtil.isNotEmpty(actions)) {
            for (String action : actions) {
                PermissionEnum permissionEnum = EnumUtil.likeValueOf(PermissionEnum.class, action);
                if (permissionEnum != null) {
                    number |= permissionEnum.getMark();
                }
            }
        }
        return StrUtil.padPre(NumberUtil.getBinaryStr(number), 8, "0");
    }

    /**
     * 转化列表中的权限
     *
     * @param resourceEntityList 资源列表
     * @param <T>                包含权限资源实体
     * @return 转化后资源列表
     */
    public static <T> List<T> covertPermission(List<T> resourceEntityList) {
        if (CollUtil.isEmpty(resourceEntityList)) {
            return Collections.emptyList();
        }
        return resourceEntityList.parallelStream().map(x -> {
            String permission = (String) ReflectUtil.getFieldValue(x, "permission");
            List<Map<String, Object>> convert = PermissionUtil.convert(permission);
            ReflectUtil.setFieldValue(x, "actionData", convert);
            List<String> action = PermissionUtil.actionFromPermission(permission);
            ReflectUtil.setFieldValue(x, "actions", action);
            return x;
        }).collect(Collectors.toList());
    }

    public static void main(String[] args) {
//        int i = ADD_PER | DELETE_PER | UPDATE_PER | SELECT_PER | IMPORT_PER | EXPORT_PER;
//        log.info("全部权限{}", i);
//        log.info("偏移后权限{},按位或权限{}", i >> 1, ADD_PER | DELETE_PER | UPDATE_PER | SELECT_PER);
//        log.info("偏移后权限{},按位或权限{}", i >> 2, ADD_PER | DELETE_PER | UPDATE_PER);
//        log.info("偏移后权限{},按位或权限{}", i >> 3, ADD_PER | DELETE_PER);
//        log.info("偏移后权限{},按位或权限{}", i >> 4, ADD_PER);
//        log.info("偏移后权限{},按位或权限{}", i >> 4, ADD_PER);
//        log.info("格式化为Map{}", BeanUtil.beanToMap(PermissionEnum.ADD_PER));
//        String s = buildPermissionString(CollUtil.toList("add"));
//        log.info("tst: {}", s);
        List<Map<String, Object>> convert = convert("00111111");
        System.out.println(convert.toString());
    }
}
